﻿#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QTimer>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLayout>
#include <QRandomGenerator>
#include <QListView>

#include "qdatetime.h"
#include "cansetmodel.h"
#include <QFileDialog>
#include <qdebug.h>
#include "cre_mes.h"

#define _TIME_ qPrintable (QTime::currentTime().toString("now :ss:zzz"))

static uint32 STDCALL  OnUDSTransmitFunc(void* ctx, const ZUDS_FRAME* frame, uint32 count)
{
    MainWindow *dlg = static_cast<MainWindow*>(ctx);
    return dlg->transmit(frame, count);
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("UDS测试程序");
    textbrw=new  QTextBrowser();
    QVBoxLayout *vxolay=new QVBoxLayout();
    QPushButton *btn=new QPushButton();
    btn->setText("清除");
    connect(btn,&QPushButton::clicked,this,&MainWindow::cleartext);
    vxolay->addWidget(textbrw);
    vxolay->addWidget(btn);
    textbrw->setFontPointSize(15);
    ui->verticalLayout->addLayout(vxolay);
    His_DTC_list.clear();

    if(type==ZLG)
    {
        candatarevthread=new QThread(this);
        canset=new CanSetModel();
        connect(this,&MainWindow::startcanrevsig,canset,&CanSetModel::DataReceive);
        connect(canset,&CanSetModel::Debug_MSG,this,&MainWindow::show_Debug);



        canset->moveToThread(candatarevthread);
        candatarevthread->start();
        IScanOPen= canset->CanConnect();
        connect(canset,&CanSetModel::DataUpdata,this,&MainWindow::RevsysFun);
        connect(canset,&CanSetModel::UDS_RevData_Sig,this,&MainWindow::Revone_UDS_fun);
        emit startcanrevsig();
    }
    if(type==GC)
    {
        MyCANControlThread=new GCcancls();
        candatarevthread_GC=new QThread();
        connect(this,&MainWindow::start_GCcanrevsig,MyCANControlThread,&GCcancls::DataReceive);
        connect(MyCANControlThread,&GCcancls::Debug_MSG,this,&MainWindow::show_Debug);
        MyCANControlThread->moveToThread(candatarevthread_GC);
        connect(MyCANControlThread,&GCcancls::DataUpdata,this,&MainWindow::RevsysFun);
        connect(MyCANControlThread,&GCcancls::UDS_RevData_Sig,this,&MainWindow::Revone_UDS_fun);
        candatarevthread_GC->start();
        IScanOPen=    MyCANControlThread->OpenCANThread(500*1000);
        emit start_GCcanrevsig();
    }
    connect(this,&MainWindow::show_Debug,this,&MainWindow::CAndebug);
    if(IScanOPen)
    {
        uds_handle_ = ZUDS_Init(DoCAN);
        ZUDS_SetTransmitHandler(uds_handle_, this, OnUDSTransmitFunc);

        ZUDS_ISO15765_PARAM tp;
        tp.block_size = 0;
        tp.fill_byte = 0;
        tp.local_st_min = 2;
        tp.is_modify_ecu_st_min = 0;
        tp.remote_st_min = 0;
        tp.frame_type = false;
        tp.version = 0;
        tp.max_data_len = VERSION_0 == tp.version ? 8 : 64; // 帧数据最长长度

        ZUDS_SetParam(uds_handle_, PARAM_TYPE_ISO15765, &tp);
        ZUDS_SESSION_PARAM sparam;
        sparam.enhanced_timeout = 5000;
        sparam.timeout = 2000;
        ZUDS_SetParam(uds_handle_, PARAM_TYPE_SESSION, &sparam);
    }


    Btn10=new QPushButton();
    Btn10->setText("切换会话");
    Btn10->setToolTip(Btn10->text());
    connect(Btn10,&QPushButton::clicked,this,&MainWindow::SessionControl_0x10_fun);

    Btn27=new QPushButton();
    Btn27->setText("安全访问");
    connect(Btn27,&QPushButton::clicked,this,&MainWindow::SecurityAccess_0x27_fun);

    CurrentDTCNumBtn=new QPushButton();
    CurrentDTCNumBtn->setText("当前故障码个数");
    CurrentDTCNumBtn->setToolTip(CurrentDTCNumBtn->text());
    connect(CurrentDTCNumBtn,&QPushButton::clicked,this,&MainWindow::CurrentDTCNumfun);
    HisDTCNumBtn=new QPushButton();
    HisDTCNumBtn->setText("历史故障码个数");
    HisDTCNumBtn->setToolTip(HisDTCNumBtn->text());
    connect(HisDTCNumBtn,&QPushButton::clicked,this,&MainWindow::HisDTCNumfun);
    CurrentDTCListBtn=new QPushButton();
    CurrentDTCListBtn->setText("当前故障码列表");
    CurrentDTCListBtn->setToolTip(CurrentDTCListBtn->text());
    connect(CurrentDTCListBtn,&QPushButton::clicked,this,&MainWindow::CurrentDTCListfun);
    HisDTCListBtn=new QPushButton();
    HisDTCListBtn->setText("历史故障码列表");
    HisDTCListBtn->setToolTip(HisDTCListBtn->text());
    connect(HisDTCListBtn,&QPushButton::clicked,this,&MainWindow::HisDTCListfun);
    supportedDTCListBtn=new QPushButton();
    supportedDTCListBtn->setText("受支持的故障码列表");
    supportedDTCListBtn->setToolTip(supportedDTCListBtn->text());
    connect(supportedDTCListBtn,&QPushButton::clicked,this,&MainWindow::supportedDTCListfun);
    SpecifiedDTCSnapshotBtn=new QPushButton();
    SpecifiedDTCSnapshotBtn->setText("快照查询");
    SpecifiedDTCSnapshotBtn->setToolTip(SpecifiedDTCSnapshotBtn->text());
    connect(SpecifiedDTCSnapshotBtn,&QPushButton::clicked,this,&MainWindow::SpecifiedDTCSnapshotfun);
    ClearDTCGroupBtn=new QPushButton();
    ClearDTCGroupBtn->setText("清除故障");
    ClearDTCGroupBtn->setToolTip(ClearDTCGroupBtn->text());
    connect(ClearDTCGroupBtn,&QPushButton::clicked,this,&MainWindow::ClearDTCGroupfun);




    UDSIDbox=new QComboBox();
    UDSIDbox->addItem("物理寻址");
    UDSIDbox->addItem("功能寻址");
    Sessionbox=new QComboBox();
    Sessionbox->addItem("默认会话");
    Sessionbox->addItem("扩展会话");
    Sessionbox->addItem("编程会话");

    DTCGroupbox=new QComboBox();
    DTCGroupbox->addItem("清除所有故障");
    DTCGroupbox->addItem("Communication DTC group – CAN");
    DTCGroupbox->addItem("Body group");
    DTCGroupbox->addItem("Chassis group");
    DTCGroupbox->addItem("Power train group");


    SecurityAccessbox=new QComboBox();
    SecurityAccessbox->addItem("扩展安全级");
    SecurityAccessbox->addItem("刷新安全级");

    DTClistbox=new QComboBox();

    //    UDS_toolbox=new QToolBox();
    //    QWidget *SessionControl

    //    ui->gridLayout_2->addWidget(UDS_toolbox);
    QSize size_temp(120,60);

    UDSID_edit=new QLineEdit;
    UDSID_edit->setMinimumSize(size_temp);
    UDSID_edit->setMaximumSize(size_temp);
    UDSID_edit->setText(QString::number(Send_UDS_CANID,16).toUpper());


    setBoxsize(Sessionbox,size_temp);
    setBoxsize(DTClistbox,size_temp);
    setBoxsize(DTCGroupbox,size_temp);
    setBoxsize(UDSIDbox,size_temp);
    setBoxsize(SecurityAccessbox,size_temp);

    setBtnsize(Btn10,size_temp);
    setBtnsize(CurrentDTCNumBtn,size_temp);
    setBtnsize(CurrentDTCListBtn,size_temp);
    setBtnsize(HisDTCNumBtn,size_temp);
    setBtnsize(HisDTCListBtn,size_temp);
    setBtnsize(supportedDTCListBtn,size_temp);
    setBtnsize(SpecifiedDTCSnapshotBtn,size_temp);
    setBtnsize(ClearDTCGroupBtn,size_temp);
    setBtnsize(Btn27,size_temp);

    ui->gridLayout_2->addWidget(UDSIDbox,0,0);
    ui->gridLayout_2->addWidget(Sessionbox,1,0);
    ui->gridLayout_2->addWidget(Btn10,1,1);
    ui->gridLayout_2->addWidget(CurrentDTCNumBtn,2,0);
    ui->gridLayout_2->addWidget(CurrentDTCListBtn,2,1);
    ui->gridLayout_2->addWidget(HisDTCNumBtn,3,0);
    ui->gridLayout_2->addWidget(HisDTCListBtn,3,1);
    ui->gridLayout_2->addWidget(supportedDTCListBtn,4,0);

    ui->gridLayout_2->addWidget(DTClistbox,5,0);
    ui->gridLayout_2->addWidget(SpecifiedDTCSnapshotBtn,5,1);
    ui->gridLayout_2->addWidget(DTCGroupbox,6,0);
    ui->gridLayout_2->addWidget(ClearDTCGroupBtn,6,1);

    ui->gridLayout_2->addWidget(SecurityAccessbox,7,0);
    ui->gridLayout_2->addWidget(Btn27,7,1);


    resize(1200,600);

}
void MainWindow::setBtnsize(QPushButton *btn,QSize size)
{
    btn->setMinimumSize(size);
    btn->setMaximumSize(size);

}
void MainWindow::setBoxsize(QComboBox *box,QSize size)
{
    box->setMinimumSize(size);
    box->setMaximumSize(size);
    QString str = "QComboBox QAbstractItemView:item\
            \n{\
            font-family: PingFangSC-Regular;\n\
            font-size:12px;\n\
            min-height:60px;\n\
            min-width:20px;\n\
}\n";
            QListView* listView = new QListView();
    box->setView(listView);
    box->setStyleSheet(str);






}



void MainWindow::SecurityAccess_0x27_fun()
{
    new Task(
                [=]()->void
    {
        //获取种子部分：
        ZUDS_REQUEST req_seed;
        memset(&req_seed, 0, sizeof(req_seed));
        req_seed.src_addr =(UDSIDbox->currentIndex()==0)?Send_UDS_CANID:Send_UDS_7DF;
        req_seed.dst_addr = Rev_UDS_CANID;
        req_seed.suppress_response = 0;
        req_seed.sid = ZUDS_SI_SecurityAccess; // 服务ID
        req_seed.param_len =1;
        req_seed.param = new uint8[req_seed.param_len];
        QString Securitylevel_str=  SecurityAccessbox->currentText().simplified();
        if(Securitylevel_str=="扩展安全级")
        {
            req_seed.param[0] = 0x01;    //扩展安全级
        }else if(Securitylevel_str=="刷新安全级"){
            req_seed.param[0] = 0x09;    //刷新安全级
        }
        ZUDS_RESPONSE resp_seed;
        ZUDS_Request(uds_handle_, &req_seed, &resp_seed);
        delete[] req_seed.param;
        quint32 CurrentSeed=0;//本次收到的种子
        quint32 Currentkey=0;//本次收到的种子
        if(resp_seed.status!=ZUDS_ERROR_OK)
        {
            UDS_STATUS_Fail(resp_seed);
            return;//发生错误后，不需要进行发送密钥
        }else {
            if (RT_POSITIVE == resp_seed.type) // 积极响应
            {
                //    qDebug()<<(tr("积极响应: 服务ID:%X, 参数长度:%d, 参数:"), resp.positive.sid, resp.positive.param_len);
                qDebug()<<"接收到安全访问种子";
                if( resp_seed.positive.param[0]==ZUDS_SI_SecurityAccess)
                {
                    CurrentSeed=resp_seed.positive.param[1]<<(8*3)+resp_seed.positive.param[2]<<(8*2)+resp_seed.positive.param[3]<<(8*1)+resp_seed.positive.param[4];
                }
            }
            else // 消极响应
            {

                qDebug()<<tr("消极响应: 1%，2%，3%").arg(    resp_seed.negative.neg_code).arg(resp_seed.negative.sid).arg(resp_seed.negative.error_code);
                return;//发生错误后，不需要进行发送密钥
            }
        }

        //发送密钥部分：
        ZUDS_REQUEST req_key;
        memset(&req_key, 0, sizeof(req_key));
        req_key.src_addr =req_seed.src_addr;
        req_key.dst_addr = Rev_UDS_CANID;
        req_key.suppress_response = 0;
        req_key.sid = ZUDS_SI_SecurityAccess; // 服务ID
        req_key.param_len =5;
        req_key.param = new uint8[req_key.param_len];
        if(Securitylevel_str=="扩展安全级")
        {
            req_key.param[0] = 0x02;    //扩展安全级
        }else if(Securitylevel_str=="刷新安全级"){
            req_key.param[0] = 0x0A;    //刷新安全级
        }

        //根据seed计算key
        req_key.param[1]=(Currentkey>>(8*3))&0xFF;
        req_key.param[2]=(Currentkey>>(8*2))&0xFF;
        req_key.param[3]=(Currentkey>>(8*1))&0xFF;
        req_key.param[4]=(Currentkey)&0xFF;



        ZUDS_RESPONSE resp_key;
        ZUDS_Request(uds_handle_, &req_key, &resp_key);
        delete[] req_key.param;

        if(resp_key.status!=ZUDS_ERROR_OK)
        {
            UDS_STATUS_Fail(resp_key);

        }else {
            if (RT_POSITIVE == resp_key.type) // 积极响应
            {
                //    qDebug()<<(tr("积极响应: 服务ID:%X, 参数长度:%d, 参数:"), resp.positive.sid, resp.positive.param_len);
                qDebug()<<"已解锁安全等级："+Securitylevel_str;

            }
            else // 消极响应
            {
                qDebug()<<tr("消极响应: 1%，2%，3%").arg(    resp_key.negative.neg_code).arg(resp_key.negative.sid).arg(resp_key.negative.error_code);

            }
        }
    } );
}

void MainWindow::SessionControl_0x10_fun()
{
    new Task(
                [=]()->void
    {
        //startSessionKeep();

        ZUDS_REQUEST req;
        memset(&req, 0, sizeof(req));
        req.src_addr =(UDSIDbox->currentIndex()==0)?Send_UDS_CANID:Send_UDS_7DF;
        req.dst_addr = Rev_UDS_CANID;
        req.suppress_response = 0;
        req.sid = ZUDS_SI_DiagnosticSessionControl; // 服务ID
        req.param_len =1;
        req.param = new uint8[req.param_len];
        QString Session_str=Sessionbox->currentText();
        if(Session_str=="默认会话")
        {
            req.param[0] = 0x01;
        }else if(Session_str=="扩展会话") {
            req.param[0] = 0x03;
        }else if(Session_str=="编程会话") {
            req.param[0] = 0x02;
        }

        ZUDS_RESPONSE resp;
        ZUDS_Request(uds_handle_, &req, &resp);
        delete[] req.param;
        if(resp.status!=ZUDS_ERROR_OK)
        {
            UDS_STATUS_Fail(resp);
        }else {
            if (RT_POSITIVE == resp.type) // 积极响应
            {
                //    qDebug()<<(tr("积极响应: 服务ID:%X, 参数长度:%d, 参数:"), resp.positive.sid, resp.positive.param_len);
                qDebug()<<"已切换到"+Session_str;

            }
            else // 消极响应
            {
                qDebug()<<tr("消极响应: 1%，2%，3%").arg(    resp.negative.neg_code).arg(resp.negative.sid).arg(resp.negative.error_code);
                qDebug()<<"消极响应";
            }
        }
    } );
}

void MainWindow::UDS_STATUS_Fail(ZUDS_RESPONSE res)//当接收状态不正常时
{
    switch (res.status)
    {
    case ZUDS_ERROR_OK:

        break;
    case ZUDS_ERROR_TIMEOUT:

        qDebug()<<"响应超时";
        break;
    case ZUDS_ERROR_TRANSPORT:

        qDebug()<<"发送帧数据失败";
        break;
    case ZUDS_ERROR_CANCEL:

        qDebug()<<"请求中止";
        break;
    case ZUDS_ERROR_SUPPRESS_RESPONSE:

        qDebug()<<"抑制响应";
        break;
    default:

        qDebug()<<"其他错误";
        break;
    }

}

MainWindow::~MainWindow()
{
    if(type==ZLG)
    {
        canset->CanClose();
        candatarevthread->quit();
        candatarevthread->wait();
    }
    if(type==GC)
    {
        MyCANControlThread->CloseCANThread();
        MyCANControlThread->stop();//停止子线程

        candatarevthread_GC->quit();
        candatarevthread_GC->wait();
    }
    if (uds_handle_ != ZUDS_INVALID_HANDLE)
    {
        ZUDS_Release(uds_handle_);
    }
    delete ui;
}

void MainWindow::RevsysFun(CanDataBase *cdb)
{
    //   showdatafun(cdb);
    return;
}

bool MainWindow::TransCAN(CanDataBase *cdb)
{
    bool Sed_result=false;
    if(type==ZLG)
    {
        Sed_result=canset->CanSend(cdb);
    }else if(type==GC)
    {
        Sed_result=MyCANControlThread->TransmitCANThread(cdb);

    }
    if( Sed_result)
    {
        showdatafun(cdb,true);
    }
    return Sed_result;
}

uint MainWindow::TransCAN(ZCAN_Transmit_Data* pTransmit, UINT len)
{
    uint sednum=0;
    if(type==ZLG)
    {
        sednum=canset->CanSend(pTransmit,len);
    }else if(type==GC)
    {
        sednum=MyCANControlThread->TransmitCANThread(pTransmit,len);

    }
    if(len==sednum)
    {
        for (UINT i = 0; i < len; ++i)
        {
            can_frame can = pTransmit[i].frame;
            canid_t id = can.can_id;

            CanDataBase *cdb = new CanDataBase();

            QByteArray arry_data;
            for (int var = 0; var < can.can_dlc; ++var) {
                arry_data.append(can.data[var]);
            }
            cdb->SetData(GET_ID(id),arry_data,can.can_dlc,IS_EFF(id),IS_RTR(id));
            showdatafun(cdb,true);
            delete cdb;
        }
    }
    return sednum;
}

void MainWindow::showdatafun(CanDataBase *cdb,bool issend)
{
    QString str;
    str.append(QDateTime::currentDateTime().toString("ss:zzz"));
    if(issend){str.append("  TX ");}else {str.append("  RX ");}
    str.append("   0x"+QString::number(cdb->Id,16).toUpper());
    str.append(" "+cdb->StrData);

    QStringList temp;temp.append(str);
    emit show_Debug(temp);


}

void MainWindow::CAndebug(QStringList strlist )
{
    for (int var = 0; var < strlist.count(); ++var) {
        textbrw->append(strlist.at(var));
    }
}

void MainWindow:: cleartext()
{
    textbrw->clear();
}

void MainWindow:: Revone_UDS_fun(CanDataBase *cdb)
{
    ZUDS_FRAME frame;
    ZCAN_ReceiveFD_Data canfd_data;
    ZCAN2UDSFrame(&frame, &cdb->ZCAN_data);
    ZUDS_OnReceive(uds_handle_, &frame);
    showdatafun(cdb,false);

    //show_Debug
}

void MainWindow::ZCAN2UDSFrame(ZUDS_FRAME* uds, const ZCAN_Receive_Data* can)
{
    memset(uds, 0, sizeof(ZUDS_FRAME));
    uds->id = GET_ID(can->frame.can_id);
    uds->extend = IS_EFF(can->frame.can_id);
    uds->remote = IS_RTR(can->frame.can_id);
    uds->data_len = can->frame.can_dlc;
    memcpy(uds->data, can->frame.data, uds->data_len);
}

void MainWindow::UDSFrame2ZCAN(ZCAN_Transmit_Data* can, const ZUDS_FRAME* uds, uint32 count)
{
    for (uint32 i = 0; i < count; ++i)
    {
        auto &can_frm = can[i];
        auto &uds_frm = uds[i];
        memset(&can_frm, 0, sizeof(ZCAN_Transmit_Data));
        can_frm.frame.can_id = MAKE_CAN_ID(uds_frm.id, uds_frm.extend, uds_frm.remote, 0);
        can_frm.frame.can_dlc = uds_frm.data_len;
        memcpy(can_frm.frame.data, uds_frm.data, uds_frm.data_len);
    }
}

uint32 MainWindow::transmit(const ZUDS_FRAME *frame, uint32 count)
{
    auto can = new ZCAN_Transmit_Data[count];
    std::unique_ptr<ZCAN_Transmit_Data[]> ptr_release{ can };
    UDSFrame2ZCAN(can, frame, count);
    return count == TransCAN( can, count) ? TRANSPORT_OK : TRANSPORT_ERROR;

}
void MainWindow::CurrentDTCNumfun()
{
    new Task(
                [=]()->void
    {
        ZUDS_REQUEST req;
        memset(&req, 0, sizeof(req));
        req.src_addr =(UDSIDbox->currentIndex()==0)?Send_UDS_CANID:Send_UDS_7DF;
        req.dst_addr = Rev_UDS_CANID;
        req.suppress_response = 0;
        req.sid = ZUDS_SI_ReadDTCInformation; // 服务ID
        req.param_len =2;
        req.param = new uint8[req.param_len];
        req.param[0] = 0x01;    //故障个数查询
        req.param[1] = 0x01;    //bit0 当前故障

        ZUDS_RESPONSE resp;
        ZUDS_Request(uds_handle_, &req, &resp);
        delete[] req.param;

        QString msg, temp;
        if(resp.status!=ZUDS_ERROR_OK)
        {
            UDS_STATUS_Fail(resp);
        }else {
            if (RT_POSITIVE == resp.type) // 积极响应
            {
                QStringList listtem;
                listtem.append("故障：Mask:0x"+QString::number(resp.positive.param[1],16).toUpper()+"  个数："+QString::number(resp.positive.param[3]*256+resp.positive.param[4]));
                emit show_Debug(listtem);
            }
            else // 消极响应
            {
                qDebug()<<tr("消极响应: 1%2%3%").arg( resp.negative.neg_code).arg(resp.negative.sid).arg(resp.negative.error_code);
            }
        }
    } );
}
void MainWindow::HisDTCNumfun()
{
    new Task(
                [=]()->void
    {

        ZUDS_REQUEST req;
        memset(&req, 0, sizeof(req));
        req.src_addr =(UDSIDbox->currentIndex()==0)?Send_UDS_CANID:Send_UDS_7DF;
        req.dst_addr = Rev_UDS_CANID;
        req.suppress_response = 0;
        req.sid = ZUDS_SI_ReadDTCInformation; // 服务ID
        req.param_len =2;
        req.param = new uint8[req.param_len];
        req.param[0] = 0x01;    //故障个数查询
        req.param[1] = 0x08;    //bit3 历史故障

        ZUDS_RESPONSE resp;
        ZUDS_Request(uds_handle_, &req, &resp);
        delete[] req.param;

        QString msg, temp;
        if(resp.status!=ZUDS_ERROR_OK)
        {
            UDS_STATUS_Fail(resp);
        }else {
            if (RT_POSITIVE == resp.type) // 积极响应
            {
                QStringList listtem;
                listtem.append("故障：Mask:0x"+QString::number(resp.positive.param[1],16).toUpper()+"  个数："+QString::number(resp.positive.param[3]*256+resp.positive.param[4]));
                emit show_Debug(listtem);
            }
            else // 消极响应
            {
                qDebug()<<tr("消极响应: 1%，2%，3%").arg(    resp.negative.neg_code).arg(resp.negative.sid).arg(resp.negative.error_code);
            }
        }
    } );
}
void MainWindow::CurrentDTCListfun()
{
    new Task(
                [=]()->void
    {

        ZUDS_REQUEST req;
        memset(&req, 0, sizeof(req));
        req.src_addr =(UDSIDbox->currentIndex()==0)?Send_UDS_CANID:Send_UDS_7DF;
        req.dst_addr = Rev_UDS_CANID;
        req.suppress_response = 0;
        req.sid = ZUDS_SI_ReadDTCInformation; // 服务ID
        req.param_len =2;
        req.param = new uint8[req.param_len];
        req.param[0] = 0x02;    //故障码查询
        req.param[1] = 0x01;    //bit0 当前故障

        ZUDS_RESPONSE resp;
        ZUDS_Request(uds_handle_, &req, &resp);
        delete[] req.param;

        QString msg, temp;
        if(resp.status!=ZUDS_ERROR_OK)
        {
            UDS_STATUS_Fail(resp);
        }else {
            if (RT_POSITIVE == resp.type) // 积极响应
            {
                QString ALLDTC_str;
                ALLDTC_str.append("故障：Mask:0x"+QString::number(resp.positive.param[1],16).toUpper());
                for (uint32 i = 0; i < (resp.positive.param_len-2)/4; ++i)
                {
                    QString DTC_One_str="DTC：0x"+QString::number(resp.positive.param[2+4*i+0],16).toUpper()+QString::number(resp.positive.param[2+4*i+1],16).toUpper()+QString::number(resp.positive.param[2+4*i+2],16).toUpper();
                    DTC_One_str.append("Status：0x"+QString::number(resp.positive.param[2+4*i+3],16).toUpper());
                    ALLDTC_str.append(DTC_One_str);
                }
                qDebug()<<ALLDTC_str;
            }
            else // 消极响应
            {
                qDebug()<<tr("消极响应: 1%，2%，3%").arg(    resp.negative.neg_code).arg(resp.negative.sid).arg(resp.negative.error_code);
            }
        }
    } );
}
void MainWindow:: HisDTCListfun()
{
    new Task(
                [=]()->void
    {

        ZUDS_REQUEST req;
        memset(&req, 0, sizeof(req));
        req.src_addr =(UDSIDbox->currentIndex()==0)?Send_UDS_CANID:Send_UDS_7DF;
        req.dst_addr = Rev_UDS_CANID;
        req.suppress_response = 0;
        req.sid = ZUDS_SI_ReadDTCInformation; // 服务ID
        req.param_len =2;
        req.param = new uint8[req.param_len];
        req.param[0] = 0x02;    //故障码查询
        req.param[1] = 0x08;    //bit3 历史故障

        ZUDS_RESPONSE resp;
        ZUDS_Request(uds_handle_, &req, &resp);
        delete[] req.param;

        QString msg, temp;
        if(resp.status!=ZUDS_ERROR_OK)
        {
            UDS_STATUS_Fail(resp);
        }else {
            if (RT_POSITIVE == resp.type) // 积极响应
            {
                QString ALLDTC_str;
                ALLDTC_str.append("故障：Mask:0x"+QString::number(resp.positive.param[1],16).toUpper())+"  ";
                His_DTC_list.clear();//清空
                for (uint32 i = 0; i < (resp.positive.param_len-2)/4; ++i)
                {
                    QString DTC_One_str="   DTC：0x"+QString("%1").arg(resp.positive.param[2+4*i+0], 2, 16, QLatin1Char('0')).toUpper()+QString("%1").arg(resp.positive.param[2+4*i+1], 2, 16, QLatin1Char('0')).toUpper()+QString("%1").arg(resp.positive.param[2+4*i+2], 2, 16, QLatin1Char('0')).toUpper();
                    His_DTC_list.append(DTC_One_str.right(6));//用于快照查询
                    DTC_One_str.append("-"+QString::number(resp.positive.param[2+4*i+3],16).toUpper());
                    ALLDTC_str.append(DTC_One_str);
                }
                UpdateDTClist_SpecifiedDTCSnapshot();//更新显示

                qDebug()<<ALLDTC_str;

            }
            else // 消极响应
            {
                qDebug()<<tr("消极响应: 1%，2%，3%").arg(    resp.negative.neg_code).arg(resp.negative.sid).arg(resp.negative.error_code);
            }
        }
    } );
}

void MainWindow:: supportedDTCListfun()
{
    new Task(
                [=]()->void
    {

        ZUDS_REQUEST req;
        memset(&req, 0, sizeof(req));
        req.src_addr =(UDSIDbox->currentIndex()==0)?Send_UDS_CANID:Send_UDS_7DF;
        req.dst_addr = Rev_UDS_CANID;
        req.suppress_response = 0;
        req.sid = ZUDS_SI_ReadDTCInformation; // 服务ID
        req.param_len =1;
        req.param = new uint8[req.param_len];
        req.param[0] = 0x0A;    //受支持的故障码查询



        ZUDS_RESPONSE resp;
        ZUDS_Request(uds_handle_, &req, &resp);
        delete[] req.param;

        QString msg, temp;
        if(resp.status!=ZUDS_ERROR_OK)
        {
            UDS_STATUS_Fail(resp);
        }else {
            if (RT_POSITIVE == resp.type) // 积极响应
            {
                QString ALLDTC_str;
                ALLDTC_str.append("故障：Mask:0x"+QString::number(resp.positive.param[1],16).toUpper());
                for (uint32 i = 0; i < (resp.positive.param_len-2)/4; ++i)
                {
                    QString DTC_One_str="DTC：0x"+QString::number(resp.positive.param[2+4*i+0],16).toUpper()+QString::number(resp.positive.param[2+4*i+1],16).toUpper()+QString::number(resp.positive.param[2+4*i+2],16).toUpper();
                    DTC_One_str.append("Status：0x"+QString::number(resp.positive.param[2+4*i+3],16).toUpper());
                    ALLDTC_str.append(DTC_One_str);
                }
                qDebug()<<ALLDTC_str;
            }
            else // 消极响应
            {
                qDebug()<<tr("消极响应: 1%，2%，3%").arg(    resp.negative.neg_code).arg(resp.negative.sid).arg(resp.negative.error_code);
            }
        }
    } );
}
void  MainWindow::SpecifiedDTCSnapshotfun()
{
    new Task(
                [=]()->void
    {

        ZUDS_REQUEST req;
        memset(&req, 0, sizeof(req));
        req.src_addr =(UDSIDbox->currentIndex()==0)?Send_UDS_CANID:Send_UDS_7DF;
        req.dst_addr = Rev_UDS_CANID;
        req.suppress_response = 0;
        req.sid = ZUDS_SI_ReadDTCInformation; // 服务ID
        req.param_len =5;
        req.param = new uint8[req.param_len];
        req.param[0] = 0x04;    //受支持的故障码查询
        QString DTC_nodeal=    DTClistbox->currentText().simplified().toUpper();
        if(DTC_nodeal.contains("0X"))
        {
            DTC_nodeal=DTC_nodeal.replace("0X","");
        }
        if(DTC_nodeal.contains("H"))
        {
            DTC_nodeal=DTC_nodeal.replace("H","");
        }
        if(DTC_nodeal.count()!=6)
        {
            qDebug()<<"DTC码错误，不可解析";
            return;
        }
        req.param[1]=DTC_nodeal.left(2).toUInt(nullptr,16)&0xFF;
        req.param[2]=DTC_nodeal.mid(2,2).toUInt(nullptr,16)&0xFF;
        req.param[3]=DTC_nodeal.right(2).toUInt(nullptr,16)&0xFF;
        int DTCSnapshotRecordNumber=1;
        req.param[4]=DTCSnapshotRecordNumber&0xFF;


        ZUDS_RESPONSE resp;
        ZUDS_Request(uds_handle_, &req, &resp);
        delete[] req.param;

        QString msg, temp;
        if(resp.status!=ZUDS_ERROR_OK)
        {
            UDS_STATUS_Fail(resp);
        }else {
            if (RT_POSITIVE == resp.type) // 积极响应
            {
                QString ALLDTC_str;
                ALLDTC_str.append("快照信息：");
                for (uint32 i = 0; i < resp.positive.param_len; ++i)
                {
                    ALLDTC_str.append(" "+QString::number(resp.positive.param[i],16).toUpper());
                }
                qDebug()<<ALLDTC_str;
            }
            else // 消极响应
            {
                qDebug()<<tr("消极响应: 1%，2%，3%").arg(    resp.negative.neg_code).arg(resp.negative.sid).arg(resp.negative.error_code);
            }
        }
    } );
}
void MainWindow:: ClearDTCGroupfun()
{
    new Task(
                [=]()->void
    {

        ZUDS_REQUEST req;
        memset(&req, 0, sizeof(req));
        req.src_addr =(UDSIDbox->currentIndex()==0)?Send_UDS_CANID:Send_UDS_7DF;
        req.dst_addr = Rev_UDS_CANID;
        req.suppress_response = 0;
        req.sid = ZUDS_SI_ClearDiagnosticInformation; // 服务ID
        req.param_len =3;
        if(DTCGroupbox->currentText()!="清除所有故障")
        {//暂不支持清除其他故障
            DTCGroupbox->setCurrentText("清除所有故障");
        }
        if(DTCGroupbox->currentText()=="清除所有故障")
        {
            req.param = new uint8[req.param_len];
            req.param[0] = 0xFF;
            req.param[1] = 0xFF;
            req.param[2] = 0xFF;
        }else    if(DTCGroupbox->currentText()=="Communication DTC group – CAN")
        {
        }else    if(DTCGroupbox->currentText()=="Body group")
        {
        }else    if(DTCGroupbox->currentText()=="Chassis group")
        {
        }else    if(DTCGroupbox->currentText()=="Power train group")
        {
        }
        ZUDS_RESPONSE resp;
        ZUDS_Request(uds_handle_, &req, &resp);
        delete[] req.param;

        QString msg, temp;
        if(resp.status!=ZUDS_ERROR_OK)
        {
            UDS_STATUS_Fail(resp);
        }else {
            if (RT_POSITIVE == resp.type) // 积极响应
            {
                qDebug()<<"故障已清除";
            }
            else // 消极响应
            {
                qDebug()<<tr("消极响应: 1%，2%，3%").arg(    resp.negative.neg_code).arg(resp.negative.sid).arg(resp.negative.error_code);
            }
        }
    } );
}

void MainWindow::UpdateDTClist_SpecifiedDTCSnapshot()//用于更新快照的选择列表
{
    qDebug()<<His_DTC_list;
    DTClistbox->addItems(His_DTC_list);

}

void MainWindow::NRC_resp(uint8 sid,uint8 nrc_code)
{
    switch (sid) {

case ZUDS_SI_DiagnosticSessionControl     ://      0x10
                break;
case ZUDS_SI_ECUReset                    ://    0x11
                break;
case ZUDS_SI_ClearDiagnosticInformation   ://    0x14
                break;
case ZUDS_SI_ReadDTCInformation           ://     0x19
                break;
case ZUDS_SI_ReadDataByIdentifier           :// 0x22
        break;
case ZUDS_SI_ReadMemoryByAddress            ://    0x23
        break;
case ZUDS_SI_ReadScalingDataByIdentifier    ://    0x24
        break;
case ZUDS_SI_SecurityAccess                   ://  0x27
        break;
case ZUDS_SI_CommunicationControl          ://     0x28
        break;
case ZUDS_SI_ReadDataByPeriodicIdentifier     ://  0x2A
        break;
case ZUDS_SI_DynamicallyDefineDataIdentifier  ://  0x2C
        break;
case ZUDS_SI_WriteDataByIdentifier          ://    0x2E
        break;
case ZUDS_SI_InputOutputControlByIdentifier  ://   0x2F
        break;
case ZUDS_SI_RoutineControl                 ://    0x31
        break;
case ZUDS_SI_RequestDownload              ://      0x34
        break;
case ZUDS_SI_RequestUpload                   ://   0x35
        break;
case ZUDS_SI_TransferData                    ://   0x36
        break;
case ZUDS_SI_RequestTransferExit           ://     0x37
        break;
case ZUDS_SI_WriteMemoryByAddress      ://         0x3D
        break;
case ZUDS_SI_TesterPresent                    ://  0x3E
        break;
case ZUDS_SI_AccessTimingParameter         ://     0x83
        break;
case ZUDS_SI_SecuredDataTransmission        ://    0x84
        break;
case ZUDS_SI_ControlDTCSetting            ://      0x85
        break;
case ZUDS_SI_ResponseOnEvent            ://        0x86
        break;
case ZUDS_SI_LinkControl                 ://       0x87
        break;

    }
}
